Skip to content

docs(changeset): the seven STACK_* codes ARE in ERROR_CODE_LEDGER — correct the stale sentence before the release compiles it - #16856

Merged
zhuangjianguo merged 1 commit into
mainfrom
claude/issue-16671-stack-envelope-changeset-prose
Sep 8, 2026
Merged

docs(changeset): the seven STACK_* codes ARE in ERROR_CODE_LEDGER — correct the stale sentence before the release compiles it#16856
zhuangjianguo merged 1 commit into
mainfrom
claude/issue-16671-stack-envelope-changeset-prose

Conversation

@claude

@claude claude Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Fixes #16671

.changeset/stack-refusal-envelopes.md is #16342's changeset, still unconsumed. Its "Not narrowed" paragraph carried this clause:

None of the six is registered in ERROR_CODE_LEDGER, for the reason the precedent was not: no wire door raises them …

It was true when it was written and is false against main today. Both changesets compile into the same release, so the published CHANGELOG.md would ship a sentence that the very same release falsifies. One sentence, one file: 1 insertion, 1 deletion.

What was measured on this tree

Worktree base 169215724; every reading below was taken here, not inherited from the card.

1. Seven codes are registered, not zero — and the count in the card is confirmed

grep -n "STACK_" packages/spec/src/api/error-code-ledger.zod.ts returns 7 rows, lines 1045–1051, sitting inside the '@objectstack/spec' array (key at line 1018; ERROR_CODE_LEDGER declared at line 176):

code in ledger
STACK_CAPABILITY_UNKNOWN yes
STACK_CROSS_REFERENCE_INVALID yes
STACK_HIERARCHY_SCOPE_CAPABILITY_REQUIRED yes
STACK_NAMESPACE_PREFIX_INVALID yes
STACK_SCHEMA_INVALID yes
STACK_SINGLE_APP_VIOLATION yes
STACK_TRIGGER_CAPABILITY_REQUIRED yes

So it is all seven — the six new codes and the STACK_CROSS_REFERENCE_INVALID precedent. The original sentence's frame ("none of the six … for the reason the precedent was not") is wrong on both halves, not one, which is why the replacement names seven rather than six.

Provenance, read from git rather than from the card: git log -S"STACK_TRIGGER_CAPABILITY_REQUIRED" -- packages/spec/src/api/error-code-ledger.zod.ts names exactly one commit, abae16adf, whose subject is "feat(spec): register every error code that ships in dist — nine door: 'none' codes enter ERROR_CODE_LEDGER under the #16404 ruling (#16449) (#16652)". Card #16449, landed as PR #16652. The corrected sentence names both.

2. The paragraph's OTHER claim is independent, and it survives

Registration in the ledger and "no wire door raises them" are different facts; only the first moved. Re-measured, with a positive control beside each zero:

reading command exit result
subject grep -rn "defineStack" packages/rest/src/ 1 0 occurrences
subject grep -rn "defineStack" packages/runtime/src/ 0 38 occurrences; 26 in non-test files, every one a comment or docstring
subject grep -rnE "import[^;]*defineStack" packages/runtime/src packages/rest/src 1 0 imports
control grep -rln "refuseUnknownQueryParams" packages/rest/src/ 0 3 files — the tree is reachable and non-empty (211 .ts files)
control grep -rnE "import[^;]*ApiErrorSchema" packages/rest/src packages/runtime/src 0 25 lines — an import-shaped grep does match over these trees

Zero call sites, zero imports, both zeros controlled. The clause "no wire door raises them — defineStack runs at authoring and boot time, and no HTTP domain handler calls it (re-measured: every non-test defineStack occurrence under packages/runtime/src and packages/rest/src is a docstring, a comment or the vocabulary table's own prose)" is therefore kept byte-for-byte, asserted by grep after the edit. The ledger's own comment on those rows records the same reading, so the registration corroborates the clause rather than displacing it — which is what the replacement says.

3. The release window is still open

ls .changeset/*.md minus README = 366 unconsumed changesets (the card's dispatch predicted 369; main moved between the two readings — not material, the window is open either way), and .changeset/stack-refusal-envelopes.md is still among them.

Does this PR need a changeset of its own? No — measured

The gate's own rule is "If it releases nothing … apply the skip-changeset label", so this was decided on a measurement:

  • The edited path is inside 0 of 81 workspace package directories. Positive control: the same predicate resolves packages/spec/src/api/error-code-ledger.zod.ts to exactly 1 directory, so the zero is a reading and not a broken check.
  • The repo-root manifest is @objectstack/spec-monorepo, private: true, no files[].
  • @objectstack/spec's files[] is dist, json-schema, liveness, prompts, llms.txt, README.md, src/**/*.zod.ts, CHANGELOG.md, api-surface, spec-changes.json — none of which reaches .changeset/.

⇒ nothing in any released package's published files[] moves. skip-changeset applied.

Worth stating explicitly because it looks like a counter-example: this diff does change text that will land in packages/spec/CHANGELOG.md, which is in files[]. It changes it as a release input already queued, not as a new release — that is the whole point of the deadline. Adding a changeset here would ship a CHANGELOG entry announcing a prose repair to another CHANGELOG entry in the same release.

Gates

Derived mechanically rather than from the dispatch list: node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack (it attests "gate list derived from the tree of 'objectstack-ai/objectstack' at commit 1692157").

17 derived / 17 run / 17 exit 0 / 0 NOT-MEASURED / 0 UNRUN, reconciled with --ran, which printed Run reconciliation — 17 derived, 17 run, 0 NOT-MEASURED, 0 UNRUN. Every exit code was captured into a variable before any pipe.

Additionally run, because the derivation flagged it explicitly (⛔ "roster under .changeset, which one of your paths is in" — its silence is evidence in neither direction there): node scripts/check-changeset-fixed.mjs → exit 0, ✓ .changeset/config.json "fixed" group is in sync with 70 public workspace packages.

No repo-wide pnpm lint narrowing is claimed: this diff contains no lintable source file. pnpm check:nul-bytes is green, and a self-scan grep -naP '[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]' over the edited file returns 0 (positive control: the same pattern matches a \x0b byte, exit 0 — note \x09 is deliberately outside the class, so a tab is not a valid control here).

验收备注 — out of scope, filed separately

⚠️ A second sentence in this same file is also false now, and it is deliberately NOT touched here. The card, the dispatch and the claim comment all scope this to one sentence, so correcting a second one would be re-adjudicating a settled boundary. It is filed instead, and it matters because it rides the same deadline.

The file's closing paragraph still says @objectstack/runtime "carries one classification row per new code in the dispatcher error-code vocabulary (door: 'none', verdict: 'boot-refusal')". Measured: grep -n "code: 'STACK_" packages/runtime/src/dispatcher-error-vocabulary.ts → exit 1, 0 rows. Positive controls in the same file with the same grep shape: verdict: 'boot-refusal' still returns 5 rows and code: ' returns 65, so the zero is a reading. Commit abae16adf — the same commit that performed the registration corrected above — ratcheted those rows out; the file now carries only a comment about the removal at line 302. Registering the codes and removing the vocabulary rows were one landing, which is exactly why fixing only the first half leaves the paragraph visibly self-inconsistent to a reviewer.

Nothing else was noted.


Generated by Claude Code

…rect the stale sentence in the stack-refusal-envelopes changeset

The unconsumed changeset .changeset/stack-refusal-envelopes.md claimed that none
of the six new STACK_* codes is registered in ERROR_CODE_LEDGER. That sentence
was true when it was written and is false against main today: all seven STACK_*
codes -- the six plus the STACK_CROSS_REFERENCE_INVALID precedent -- are now
registered under the '@objectstack/spec' key of ERROR_CODE_LEDGER.

Measured on this tree, not inherited:

  grep -n "STACK_" packages/spec/src/api/error-code-ledger.zod.ts
    -> 7 rows, lines 1045-1051, inside the '@objectstack/spec' array (key at
       line 1018; ERROR_CODE_LEDGER declared at line 176)

The paragraph's OTHER claim -- that no wire door raises these codes -- is
independent of the registration and survives re-measurement unchanged, so it is
kept verbatim:

  grep -rn "defineStack" packages/rest/src/     -> exit 1, 0 occurrences
  grep -rn "defineStack" packages/runtime/src/  -> 38 occurrences, 26 in
       non-test files, every one a comment or docstring; 0 call sites, 0 imports

Both zero readings carry positive controls: the same invocation finds
refuseUnknownQueryParams in packages/rest/src (3 files) and finds defineStack
in packages/runtime/src, and an import-shaped grep for ApiErrorSchema over the
same two trees returns 25 lines.

One sentence, one file. The message text, the refusal table, the semver
argument and the "Not narrowed" framing are untouched.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016N6xmWt5hYm94ffVEwGH8x
@claude

claude Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor Author

Readied and armed — every name on this head is completed with success/skipped

domain:spec execution seat, session session_016N6xmWt5hYm94ffVEwGH8x, 2026-09-08T11:09:32Z. Head ff65e5fdf.

Enqueue criterion, read the way it has to be read: all 25 distinct check names, aggregated by name, are completed with success or skipped. ⛔ "Nothing is red yet" is not that reading, and a same-head duplicate (one superseded run plus its replacement) is why the aggregation is by name rather than by row.

No gate stands over it: check-governed-merges.mjs --test on this PR's file list — NOT governed, derived from the register, not recalled. Clause-②: no, and the one changed path is .changeset/**, which does not hit the enqueue gate's PATH limb (packages/spec/src/**) — so ⛔ no at-tier contract review is owed here, unlike its three siblings on this wave.

Draft flipped, auto-merge armed. The queue merges it.

⚠️ What is NOT finished when this merges — the same paragraph carries a second false sentence, filed by this PR's own dev as #16857: the changeset claims @objectstack/runtime carries one boot-refusal classification row per new code, and the same commit abae16adf that performed the registration ratcheted all seven rows out. Verified independently by this seat on origin/main: code: 'STACK_0 rows in packages/runtime/src/dispatcher-error-vocabulary.ts, with controls in the same file firing (verdict: 'boot-refusal' → 14, code: ' → 83).

#16857 is this seat's, strictly sequenced after this PR merges (same paragraph, so a parallel edit would conflict), and it is on the same release deadline: the changeset is still unconsumed, and it stops being correctable when a release compiles it.


Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/xs skip-changeset PR has no user-facing published change; bypasses the changeset gate tooling

Projects

None yet

2 participants